home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Suzy B Software 2
/
Suzy B Software CD-ROM 2 (1994).iso
/
extras
/
programm
/
a56
/
src
/
keybld.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-27
|
4KB
|
231 lines
/*
* Copyright (C) 1990-1994 Quinn C. Jensen
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. The author makes no representations
* about the suitability of this software for any purpose. It is
* provided "as is" without express or implied warranty.
*
*/
static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
/*
* keybld - builds a finite-state parser for the given keyword list
*
*/
#include <stdio.h>
#include "a56.h"
char buf[1024];
main()
{
int line = 0;
while(gets(buf)) {
char *bp = buf;
line++;
while(*bp != '\t' && *bp != ' ') bp++;
*bp++ = '\0';
while(*bp == '\t' || *bp == ' ') bp++;
if(strcmp(buf, ".code") == 0) {
printf("%s\n", bp);
} else if(add_tok(buf, bp) == -1) {
fprintf(stderr, "input line %d: ambiguous\n", line);
}
}
dump_machine();
return 0;
}
#define MAX_CHAR 'z'
#define TRANSITIONS (MAX_CHAR + 1)
struct state {
int number;
char *seen;
struct trans {
char action;
void *arg;
} trans[TRANSITIONS];
struct state *next;
} empty_state, *stop = NULL, *scur = NULL, *new_state();
int n_states = 0;
/* actions */
#define NOMATCH 0 /* argument is nothing */
#define GOTO 1 /* argument is target state */
#define TERMINAL 2 /* argument is which user action to perform */
struct user_action {
char *action;
struct user_action *next;
} *utop = NULL, *ucur = NULL;
int n_user_actions = 0;
add_tok(tok, actions)
char *tok, *actions;
{
struct state *scur;
struct user_action *unew = (struct user_action *)alloc(sizeof *unew);
unew->action = strsave(actions);
unew->next = NULL;
if(ucur)
ucur->next = unew;
ucur = unew;
if(utop == NULL)
utop = unew;
if(stop == NULL)
new_state(NULL);
if(follow(*tok, tok + 1, stop) == -1)
return -1;
n_user_actions++;
return 0;
}
follow(c, tp, sp)
char c;
char *tp;
struct state *sp;
{
struct trans *arcp, *arcup;
if(c >= 'a' && c <= 'z') {
c -= 'a' - 'A';
}
arcp = sp->trans + c;
if(c >= 'A' && c <= 'Z') {
arcup = sp->trans + c + 'a' - 'A';
} else {
arcup = arcp;
}
if(c == '\0') {
if(arcp->action == TERMINAL) {
return -1;
} else {
arcp->action = arcup->action = TERMINAL;
arcp->arg = arcup->arg = (void *)n_user_actions;
return 0;
}
} else {
if(arcp->action == GOTO) {
return follow(*tp, tp + 1, arcp->arg);
} else {
struct state *new = new_state(tp);
arcp->action = arcup->action = GOTO;
arcp->arg = arcup->arg = (void *)new;
return follow(*tp, tp + 1, new);
}
}
}
struct state *new_state(tp)
char *tp;
{
struct state *snew = (struct state *)alloc(sizeof *snew);
char tmp[1024];
*snew = empty_state;
snew->number = n_states++;
snew->next = NULL;
if(scur)
scur->next = snew;
scur = snew;
if(stop == NULL)
stop = snew;
if(tp)
strncpy(tmp, buf, tp - buf);
else
strcpy(tmp, "<nothing>");
snew->seen = strsave(tmp);
return snew;
}
dump_machine()
{
struct state *sp;
struct user_action *up;
int n, a;
printf("/* state machine generated by keybld */\n");
printf("/* states=%d actions=%d */\n", n_states, n_user_actions);
printf("/* %d bytes required for transition table storage */\n",
sizeof(short) * TRANSITIONS * n_states);
printf("short transitions[%d][%d] = {\n", n_states, TRANSITIONS);
for(n = 0, sp = stop; sp; sp = sp->next, n++) {
printf(" /* state %d: \"%s\" */\n", n, sp->seen);
printf(" {");
for(a = 0; a < TRANSITIONS; a++) {
struct trans *tp = sp->trans + a;
switch(tp->action) {
case GOTO:
printf("%d", ((struct state *)tp->arg)->number);
break;
case TERMINAL:
printf("%d", -(int)tp->arg - 1);
break;
case NOMATCH:
printf("0");
break;
}
printf(",%s", a % 20 == 19 ? "\n\t\t" : "");
};
printf("},\n");
}
printf("};\n");
printf("\
\n\
kparse(kp)\n\
char *kp;\n\
{\n\
int state = 0;\n\
\n\
for(;;) {\n\
short transition = transitions[state][*kp];\n");
printf("\
if(transition == 0) {\n\
return 0;\n\
} else if(transition > 0) {\n\
kp++;\n\
state = transition;\n\
} else {\n\
switch(-transition) {\n");
for(n = 1, up = utop; up; up = up->next, n++) {
printf("\
case %d:\n\
%s;\n\
break;\n", n, up->action);
}
printf("\
}\n\
return transition;\n\
}\n\
}\n\
}\n");
}